package tcln.gxtx.client.widget.treegrid.renderer;

import tcln.gxtx.client.widget.treegrid.TreeGridExtension;

import com.extjs.gxt.ui.client.data.ModelData;
import com.extjs.gxt.ui.client.store.ListStore;
import com.extjs.gxt.ui.client.store.TreeStore;
import com.extjs.gxt.ui.client.widget.grid.ColumnData;
import com.extjs.gxt.ui.client.widget.grid.Grid;
import com.extjs.gxt.ui.client.widget.treegrid.TreeGridCellRenderer;
import com.extjs.gxt.ui.client.widget.treepanel.TreePanel.Joint;
import com.google.gwt.user.client.ui.AbstractImagePrototype;

/**
 * Base class renderers used in tree grids. This class differs from
 * {@link com.extjs.gxt.ui.client.widget.treegrid.TreeGridCellRenderer} shipped with ExtGWT in that it allows to format
 * model property to show correct data according to specific contexts.
 * <p>
 * <b>Remark</b>: This renderer customizes the formatting of model data ONLY IF the owner treegrid implements interface
 * {@link TreeGridExtension}. Otherwise, the default behavior defined in {@link TreeGridCellRenderer} will be used.
 * 
 * @param <M>
 *            the model type
 * @author Truong Chau Lien Ngoc (lienngoc@gmail.com)
 */
public abstract class AbstractTreeGridCellRenderer<M extends ModelData> extends TreeGridCellRenderer<M> {

    /**
     * {@inheritDoc}
     */
    @Override
    public Object render(final M model, final String property, final ColumnData config, final int rowIndex,
            final int colIndex, final ListStore<M> store, final Grid<M> grid) {
        if (grid instanceof TreeGridExtension<?>) {
            config.css = "x-treegrid-column";

            @SuppressWarnings("unchecked")
            TreeGridExtension<M> tree = (TreeGridExtension<M>) grid;

            TreeStore<M> ts = tree.getTreeStore();
            Joint j = tree.calcualteJoint(model);
            AbstractImagePrototype iconStyle = tree.calculateIconStyle(model);
            int level = calculateModelDepth(ts, model);

            String text = formatModelData(model, property);
            String id = tree.findNodeId(model);
            return tree.getTreeView().getTemplate(model, id, text, iconStyle, false, j, level - 1);

        } else {
            return super.render(model, property, config, rowIndex, colIndex, store, grid);
        }
    }

    /**
     * Calculates given model's depth for rendering. In some cases, the depth of a model to be used for rendering is not
     * the same as the that of this model.
     * 
     * @param treestore
     * @param model
     * @return
     */
    protected int calculateModelDepth(TreeStore<M> treestore, M model) {
        return treestore.getDepth(model);
    }

    /**
     * Formats data before rendering the text portion in a cell.
     * 
     * @param model
     * @param property
     * @return
     */
    protected abstract String formatModelData(M model, String property);
}
